﻿using PlutoStudio.Diagnostics;
using PlutoStudio.Net.Configuration;
using PlutoStudio.Net.Messages;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace PlutoStudio.Net.Tcp
{
    public class TcpListener
    {
        private static TraceHelper trace = new TraceHelper("PlutoStudio.Net.Trace", "Default Trace.");
        private Socket socket;
        private SocketAsyncEventArgs args;
        public event AcceptedEventHandler Accepted;
        public IMessageGenerater Generater { get; set; }

        public TcpListener()
            : this(ConfigurationManager.Listener.IPAddress, ConfigurationManager.Listener.Port, ConfigurationManager.Listener.MaxConnections)
        {

        }

        public TcpListener(IPAddress address, int port, int backlog)
            : this(new IPEndPoint(address, port), backlog)
        {

        }

        public TcpListener(IPEndPoint endPoint, int backlog)
        {
            args = new SocketAsyncEventArgs();
            args.Completed += Completed;
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            socket.Bind(endPoint);
            socket.Listen(backlog);
            Generater = new MessageProvider();
        }

        void Completed(object sender, SocketAsyncEventArgs e)
        {
            ProcessAccept();
        }

        public void StartAccept()
        {
            args.AcceptSocket = null;
            var willRaiseEvent = socket.AcceptAsync(args);
            if (!willRaiseEvent)
            {
                ProcessAccept();
            }
        }

        private void ProcessAccept()
        {
            if (args.SocketError!= SocketError.Success)
            {
                trace.TraceInformation("监听连接发生错误!");
                return;
            }
            var socket = args.AcceptSocket;
            var client = new TcpClient(socket);
            client.Generater = Generater;
            trace.TraceInformation("接受到来自{0}的连接!", client.RemoteEndPoint);
            OnAccept(client);
            StartAccept();
        }

        private void OnAccept(TcpClient client)
        {
            var e = new AcceptedEventArgs(client);
            OnAccept(e);
        }

        protected virtual void OnAccept(AcceptedEventArgs e)
        {
            if (Accepted!=null)
            {
                Accepted(this, e);
            }
        }


        public void Stop()
        {
            socket.Close();
        }
    }
}
